package net.ak.controller;

import java.util.Date;
import java.util.List;

import net.ak.constant.Constant;
import net.ak.constant.USER_STATUS;
import net.ak.model.Category;
import net.ak.model.User;
import net.ak.response.AKResponse;
import net.ak.service.CategoryService;
import net.ak.service.UserService;
import net.ak.session.SessionManagerment;
import net.ak.session.UserTO;

import org.apache.commons.validator.EmailValidator;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@SuppressWarnings("deprecation")
@Controller
@RequestMapping("/apis/user")
public class UserController extends BaseController {
	
	@Autowired
	private UserService userService;
	
	@Autowired
	private CategoryService categoryService;
	
	private final static ObjectMapper mapper = new ObjectMapper();
	
	private final static SessionManagerment sessionManagerment = SessionManagerment.getInstance();
	
	/**
	 * 1.	Authentication Interface
	 * 
	 * This method is used to login into system
	 * @param username
	 * @param password
	 * @return
	 */
	@RequestMapping(value = "/authenticate", method = RequestMethod.POST)
	public @ResponseBody AKResponse authenticate(@RequestParam String u, @RequestParam String p, @RequestParam String lat, @RequestParam String lng) {
		AKResponse akResponseSuccess = new AKResponse(Constant.SUCCESS_CODE, Constant.SUCCESS_MESSAGE);
		System.out.println("u --> " + u);
		System.out.println("p --> " + p);
		User user = userService.getUserByEmailAndPassword(u, p);
		
		//1. check valid email or pass
		if (user == null) {
			return new AKResponse(Constant.INVALID_LOGIN_CODE, Constant.INVALID_LOGIN_MESSAGE);
		}
		
		//2. check user is active
		if (sessionManagerment.isActive(user.getEmail())) {
			return new AKResponse(Constant.ACTIVE_SESSION_CODE, Constant.ACTIVE_SESSION_MESSAGE);
		}
		
		//3. ok
		//update lat and long and set user is online
		user.setLatitude(Double.parseDouble(lat));
		user.setLongitude(Double.parseDouble(lng));
		userService.saveOrUpdate(user);
		
		//init session
		sessionManagerment.initSession(user);
		UserTO userTO = sessionManagerment.getUser(user.getEmail());
		akResponseSuccess.setResponseData(convertObjectToString(userTO));
		return akResponseSuccess;
	}
	
	
	/**
	 * 2.	Forgot Password Interface
	 * This method is used to call when user forgot user's password
	 * @param email
	 * @return
	 */
	@RequestMapping(value = "/forgotPassword", method = RequestMethod.POST)
	@ResponseBody
	public AKResponse forgotPassword(@RequestParam String email) {
		AKResponse akResponseSuccess = new AKResponse(Constant.SUCCESS_CODE, Constant.SUCCESS_MESSAGE);
		
		//call send mail service
		
		return akResponseSuccess;
	}
	
	/**
	 * 3.	Registration Interface
	 * This method is used when user register in the system.
	 * @param email
	 * @param password
	 * @param usertype
	 * @return
	 */
	@RequestMapping(value = "/register", method = RequestMethod.POST)
	public @ResponseBody AKResponse register(
			@RequestParam String u, @RequestParam String email, @RequestParam String p,
			@RequestParam String lat, @RequestParam String longt, @RequestParam String phone,
			@RequestParam String paypalEmail, @RequestParam String desc, 
			@RequestParam String isPublicPhoneNumber, @RequestParam String bankAccount
			) {
		AKResponse akResponseSuccess = new AKResponse(Constant.SUCCESS_CODE, Constant.SUCCESS_MESSAGE);
		
		//1. verify email
		boolean verifyEmail = EmailValidator.getInstance().isValid(email);
		if (!verifyEmail) {
			AKResponse akResponseInvalidEmail = new AKResponse(Constant.INVALID_EMAIL_CODE, Constant.INVALID_EMAIL_MESSAGE);
			return akResponseInvalidEmail;
		}
		
		//2. check exist email.
		verifyEmail = userService.getUserByEmail(email) == null ? true : false;
		if (!verifyEmail) {
			AKResponse akResponseInvalidEmail = new AKResponse(Constant.INVALID_EMAIL_CODE, Constant.EXIST_EMAIL_MESSAGE);
			return akResponseInvalidEmail;
		}
		
		//3. check exist user name
		
		//4. check paypalEmail
		
		//5. check phone
		
		//6. check latitude, longitude
		
		
		User user = new User();
		user.setUsername(u);
		user.setEmail(email);
		user.setPassword(p);
		user.setLatitude(Double.parseDouble(lat));
		user.setLongitude(Double.parseDouble(longt));
		user.setPhone(phone);
		user.setBankAccount(bankAccount);
		user.setDescription(desc);
		user.setIsPublicPhoneNumber(isPublicPhoneNumber);
		
		user.setCreatedDate(new Date());
		user.setUpdatedDate(new Date());
		user.setRegistedDate(new Date());
		user.setOnline(true);
		user.setStatus(USER_STATUS.DEACTIVED);
		
		
		
		userService.saveOrUpdate(user);
		
		User us = userService.getUserByEmail(email);
		sessionManagerment.initSession(us);
		
		return akResponseSuccess;
		
	}
	
	
	/**
	 * 4.	Logout Interface
	 * This method is user to logout.
	 * @param session
	 * @return
	 */
	@RequestMapping(value = "/logout", method = RequestMethod.GET)
	@ResponseBody
	public AKResponse logout(@RequestParam String session) {
		AKResponse akResponseSuccess = new AKResponse(Constant.SUCCESS_CODE, Constant.SUCCESS_MESSAGE);
		return akResponseSuccess;
	}
	
	
	
	/**
	 * 5.	Get All Category Interface
	 * This method is used to get all {@link Category}.
	 * @return
	 */
	@RequestMapping(value = "/getAllCategory", method = RequestMethod.GET)
	public @ResponseBody AKResponse getAllCategory(@RequestParam String session) {
		//1. verify session
		if(!sessionManagerment.verifySession(session).equalsIgnoreCase("200")) {
			AKResponse akResponseError = new AKResponse(sessionManagerment.getErrorCode(), sessionManagerment.getErrorMessage());
			return akResponseError;
		} else {
			//2. return all category
			AKResponse akResponseSuccess = new AKResponse(Constant.SUCCESS_CODE, Constant.SUCCESS_MESSAGE);
			akResponseSuccess.setResponseData(convertObjectToString(categoryService.listCategories()));
			return akResponseSuccess;
		}
	}
	
	
	/**
	 * 6.	Select Category Interface
	 * 
	 * This method is used to get category by id.
	 * @param session
	 * @param catId
	 * @return
	 */
	@RequestMapping(value = "/selectCategory", method = RequestMethod.GET)
	@ResponseBody
	public AKResponse selectCategory(@RequestParam String session, @RequestParam Long catId) {
		//1. vefify session
		if(!sessionManagerment.verifySession(session).equalsIgnoreCase("200")) {
			AKResponse akResponseError = new AKResponse(sessionManagerment.getErrorCode(), sessionManagerment.getErrorMessage());
			return akResponseError;
		}
		// return category
		Category category 			 = categoryService.getCategoryById(catId);
		AKResponse akResponseSuccess = new AKResponse(Constant.SUCCESS_CODE, Constant.SUCCESS_MESSAGE);
		akResponseSuccess.setResponseData(convertObjectToString(category));
		
		return akResponseSuccess;
	}
	
	
	
	/**
	 * 7.	Category Registration Interface
	 * 
	 * This method is used to add category for {@link User}.
	 * @param email
	 * @param categoryName
	 * @return
	 */
	@RequestMapping(value = "/registerCategory", method = RequestMethod.POST)
	public @ResponseBody AKResponse registerCategory(@RequestParam String session, @RequestParam Long catId, @RequestParam String cost,
			@RequestParam String paypalEmail, @RequestParam String desc
			) {
		System.out.println("session:" + session);
		//1. check session
		if(!sessionManagerment.verifySession(session).equalsIgnoreCase("200")) {
			AKResponse akResponseError = new AKResponse(sessionManagerment.getErrorCode(), sessionManagerment.getErrorMessage());
			return akResponseError;
		}
		//2. check cost
		
		//3. paypalEmail
		
		//4. add category
		AKResponse akResponseSuccess 	= new AKResponse(Constant.SUCCESS_CODE, Constant.SUCCESS_MESSAGE);
		User user 						= sessionManagerment.getUser(sessionManagerment.getEmail(session)).getUser();
		Category category 				= categoryService.getCategoryById(catId);
		
		userService.addUserCategory(user, category, desc, cost);
		return akResponseSuccess;
	}
	
	/**
	 * 8.	Get all Users by Category Interface
	 * 
	 * This method is used to get all user by category.
	 * @param session
	 * @param catId
	 * @return
	 */
	@RequestMapping(value = "/listUsersByCategory", method = RequestMethod.GET)
	public @ResponseBody AKResponse listUsersByCategory(@RequestParam String session, @RequestParam Long catId) {
		//1. check session
		if(!sessionManagerment.verifySession(session).equalsIgnoreCase("200")) {
			AKResponse akResponseError = new AKResponse(sessionManagerment.getErrorCode(), sessionManagerment.getErrorMessage());
			return akResponseError;
		}
		//2. get all user by category
		AKResponse akResponseSuccess 	= new AKResponse(Constant.SUCCESS_CODE, Constant.SUCCESS_MESSAGE);
		List<User> users 				= userService.listUsersByCategory(catId);
		akResponseSuccess.setResponseData(users);
		return akResponseSuccess;
	}
	
	/**
	 * This method is used to get profile of user.
	 * @param session
	 * @return
	 */
	@RequestMapping(value = "/getUserProfile", method = RequestMethod.GET)
	public @ResponseBody AKResponse getUserProfile(@RequestParam String session) {
		//1. check session
		if(!sessionManagerment.verifySession(session).equalsIgnoreCase("200")) {
			AKResponse akResponseError = new AKResponse(sessionManagerment.getErrorCode(), sessionManagerment.getErrorMessage());
			return akResponseError;
		}
		//2. update user
		AKResponse akResponseSuccess 	= new AKResponse(Constant.SUCCESS_CODE, Constant.SUCCESS_MESSAGE);
		User user 						= new User();
		akResponseSuccess.setResponseData(user);
		return akResponseSuccess;
	}
	
	
	/**
	 * 10.	Update Current Zipcode Interface
	 * 
	 * This method is used to update zip code
	 * @param session
	 * @return
	 */
	@RequestMapping(value = "/updateZipcode", method = RequestMethod.POST)
	public @ResponseBody AKResponse updateZipcode(@RequestParam String session, @RequestParam String zip) {
		//1. check session
		if(!sessionManagerment.verifySession(session).equalsIgnoreCase("200")) {
			AKResponse akResponseError = new AKResponse(sessionManagerment.getErrorCode(), sessionManagerment.getErrorMessage());
			return akResponseError;
		}
		//2. update user
		AKResponse akResponseSuccess 	= new AKResponse(Constant.SUCCESS_CODE, Constant.SUCCESS_MESSAGE);
		User user 						= new User();
		//set ZipCode
		
		userService.saveOrUpdate(user);
		akResponseSuccess.setResponseData(user);
		return akResponseSuccess;
	}
	
	
	/**
	 * 12.	Update Email Interface
	 * 
	 * This method is used to update email
	 * @param session
	 * @return
	 */
	@RequestMapping(value = "/updateEmail", method = RequestMethod.POST)
	public @ResponseBody AKResponse updateEmail(@RequestParam String session, @RequestParam String e) {
		//1. check session
		if(!sessionManagerment.verifySession(session).equalsIgnoreCase("200")) {
			AKResponse akResponseError = new AKResponse(sessionManagerment.getErrorCode(), sessionManagerment.getErrorMessage());
			return akResponseError;
		}
		//2. update user
		AKResponse akResponseSuccess 	= new AKResponse(Constant.SUCCESS_CODE, Constant.SUCCESS_MESSAGE);
		User user 						= new User();
		//set email
		
		userService.saveOrUpdate(user);
		akResponseSuccess.setResponseData(user);
		return akResponseSuccess;
	}
	
	/**
	 * 13.	Update User Paypal Email Interface
	 * 
	 * This method is used to update paypal email
	 * @param session
	 * @return
	 */
	@RequestMapping(value = "/updatePaypalEmail", method = RequestMethod.POST)
	public @ResponseBody AKResponse updatePaypalEmail(@RequestParam String session, @RequestParam String paypalEmail) {
		//1. check session
		if(!sessionManagerment.verifySession(session).equalsIgnoreCase("200")) {
			AKResponse akResponseError = new AKResponse(sessionManagerment.getErrorCode(), sessionManagerment.getErrorMessage());
			return akResponseError;
		}
		//2. update user
		AKResponse akResponseSuccess 	= new AKResponse(Constant.SUCCESS_CODE, Constant.SUCCESS_MESSAGE);
		User user 						= new User();
		//set email
		
		userService.saveOrUpdate(user);
		akResponseSuccess.setResponseData(user);
		return akResponseSuccess;
	}
	
	/**
	 * 14.	Update User Password Interface
	 * 
	 * This method is used to update password
	 * @param session
	 * @return
	 */
	@RequestMapping(value = "/updatePassword", method = RequestMethod.POST)
	public @ResponseBody AKResponse updatePassword(@RequestParam String session, @RequestParam String newP, @RequestParam String oldP) {
		//1. check session
		if(!sessionManagerment.verifySession(session).equalsIgnoreCase("200")) {
			AKResponse akResponseError = new AKResponse(sessionManagerment.getErrorCode(), sessionManagerment.getErrorMessage());
			return akResponseError;
		}
		//2. check old password
		
		//3. update user
		AKResponse akResponseSuccess 	= new AKResponse(Constant.SUCCESS_CODE, Constant.SUCCESS_MESSAGE);
		User user 						= new User();
		//set new password
		
		userService.saveOrUpdate(user);
		akResponseSuccess.setResponseData(user);
		return akResponseSuccess;
	}
	
	/**
	 * 15.	Update User Category Interface
	 * 
	 * This method is used to User update user's category.
	 * @param session
	 * @return
	 */
	@RequestMapping(value = "/updateCategory", method = RequestMethod.POST)
	public @ResponseBody AKResponse updateCategory(@RequestParam String session, @RequestParam Long catId, @RequestParam String cost,
			@RequestParam String paypalEmail, @RequestParam String desc
			) {
		//1. check session
		if(!sessionManagerment.verifySession(session).equalsIgnoreCase("200")) {
			AKResponse akResponseError = new AKResponse(sessionManagerment.getErrorCode(), sessionManagerment.getErrorMessage());
			return akResponseError;
		}
		//2. check cost
		
		//3. paypalEmail
		
		//4. add category
		AKResponse akResponseSuccess 	= new AKResponse(Constant.SUCCESS_CODE, Constant.SUCCESS_MESSAGE);
		User user 						= new User(); //get from session
		Category category 				= categoryService.getCategoryById(catId);
		
		userService.addUserCategory(user, category, desc, cost);
		return akResponseSuccess;
	}
	
	/**
	 * 16.	Update User Bank Account Interface
	 * 
	 * This method is used to update paypal email
	 * @param session
	 * @return
	 */
	@RequestMapping(value = "/updateBankAccount", method = RequestMethod.POST)
	public @ResponseBody AKResponse updateBankAccount(@RequestParam String session, @RequestParam String bankAccount) {
		//1. check session
		if(!sessionManagerment.verifySession(session).equalsIgnoreCase("200")) {
			AKResponse akResponseError = new AKResponse(sessionManagerment.getErrorCode(), sessionManagerment.getErrorMessage());
			return akResponseError;
		}
		//2. update user
		AKResponse akResponseSuccess 	= new AKResponse(Constant.SUCCESS_CODE, Constant.SUCCESS_MESSAGE);
		User user 						= new User();
		//set email
		
		userService.saveOrUpdate(user);
		akResponseSuccess.setResponseData(user);
		return akResponseSuccess;
	}
	
	/**
	 * This method is used to convert object to String
	 * @param obj
	 * @return
	 */
	private String convertObjectToString(Object obj) {
		try {
			return mapper.writeValueAsString(obj);
		} catch (Exception ex) {}
		
		return null;
	}
	
}
